using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.IO;
using BlogEngine.Core;

namespace Controls
{
    public class PageMenu : Control
    {
        static PageMenu()
        {
            BlogEngine.Core.Page.Saved += delegate { _Html = null; };
        }

        #region Properties

        private static object _SyncRoot = new object();
        private static string _Html;
        private bool _defaultAdded = false;
        string _curPage = HttpUtility.UrlEncode(GetPageName(HttpContext.Current.Request.RawUrl.ToLower()));

        private string Html
        {
            get
            {
                if (_Html == null)
                {
                    lock (_SyncRoot)
                    {
                        if (_Html == null)
                        {
                            HtmlGenericControl ul = BindPages();
                            System.IO.StringWriter sw = new System.IO.StringWriter();
                            ul.RenderControl(new HtmlTextWriter(sw));
                            _Html = sw.ToString();
                        }
                    }

                }

                return _Html;
            }
        }

        #endregion

        private HtmlGenericControl BindPages()
        {
            //create the container
            HtmlGenericControl div = new HtmlGenericControl("div");
            div.ID = "pagemenu";

            //recursively get all children
            CreateMenuItems(div, Guid.Empty);

            //lastly make sure the standard entries are at the top (if not already) and insert contact at end 
            AddDefaultEntries(div);

			if (div.Controls.Count > 0)
				div.Controls[0].Controls.Add(AddMenuItem(Resources.labels.contact, "~/contact.aspx"));

            return div;
        }

        private void CreateMenuItems(HtmlGenericControl container, Guid parentId)
        {
            //no children so return
            if (!HasChildren(parentId))
                return;

            HtmlGenericControl ul = new HtmlGenericControl("ul");
            AddDefaultEntries(ul);

            List<BlogEngine.Core.Page> items = BlogEngine.Core.Page.Items.FindAll(delegate(BlogEngine.Core.Page item)
            {
                return (item.ShowInList && item.IsVisible && item.Parent == parentId);
            });

            items.Sort();

            foreach (BlogEngine.Core.Page page in items)
            {
                HtmlGenericControl li = AddMenuItem(page.Title, page.RelativeLink);
                CreateMenuItems(li, page.Id);
                ul.Controls.Add(li);
            }

            container.Controls.Add(ul);
        }

        private void AddDefaultEntries(HtmlGenericControl container)
        {
            //make sure the default start entries are always added
            if (!_defaultAdded)
            {
                HtmlGenericControl ul = container;

                //handle scenario where there are no pages so we end up with the wrapper div
                if (container.TagName != "ul")
                {
                    ul = new HtmlGenericControl("ul");
                }

                ul.Controls.Add(AddMenuItem(Resources.labels.home, "~/default.aspx"));
                ul.Controls.Add(AddMenuItem(Resources.labels.archive, "~/archive.aspx"));
                _defaultAdded = true;
            }
        }

        private HtmlGenericControl AddMenuItem(string pageName, string pageUrl)
        {
            HtmlGenericControl li = new HtmlGenericControl("li");
            HtmlAnchor anc = new HtmlAnchor();

            //            string pageName = HttpUtility.UrlEncode(GetPageName(page.RelativeLink.ToString().ToLower()));
            anc.HRef = pageUrl;
            anc.InnerHtml = "<span>" + pageName + "</span>";
            anc.Title = pageName;

            if (GetPageName(pageUrl).ToLower() == _curPage.ToLower())
            {
                anc.Attributes.Add("class", "current");
            }

            li.Controls.Add(anc);
            return li;
        }

        private bool HasChildren(Guid pageId)
        {
            bool returnValue = false;

            foreach (BlogEngine.Core.Page page in BlogEngine.Core.Page.Items)
            {
                if (page.ShowInList && page.IsPublished)
                {
                    if (page.Parent == pageId)
                    {
                        returnValue = true;
                        break;
                    }
                }
            }

            return returnValue;
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            writer.WriteLine(Html);
        }

        private static string GetPageName(string requestPath)
        {
            if (requestPath.IndexOf('?') != -1)
                requestPath = requestPath.Substring(0, requestPath.IndexOf('?'));
            return requestPath.Remove(0, requestPath.LastIndexOf("/") + 1).ToLower();
        }

    }
}